package com.imot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.imot.handler.ImotExciption;
import com.imot.mapper.EmaExceptionRecordMapper;
import com.imot.mapper.EmaRecordMapper;
import com.imot.mapper.TargetParametersMapper;
import com.imot.pojo.entity.Dict;
import com.imot.pojo.entity.EmaErrorRecord;
import com.imot.pojo.entity.EmaRecord;
import com.imot.pojo.entity.ErrorRecord;
import com.imot.pojo.enums.DateEnum;
import com.imot.pojo.vo.DataAssetVo;
import com.imot.pojo.vo.ExceptionDetailVo;
import com.imot.pojo.vo.MonitorWaveVo;
import com.imot.pojo.vo.WorkChekcVo;
import com.imot.response.Result;
import com.imot.service.*;
import com.sun.jndi.cosnaming.ExceptionMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ClassName: StatusSituationServiceImpl
 * Description:
 * date: 2023/11/29 10:55
 *
 * @author imot-jiah.wang
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StatusSituationServiceImpl implements StatusSituationService {
    private final ITargetParametersService targetParametersService;
    private final IErrorRecordService errorRecordService;
    private final IEmaRecordService recordService;
    private final IDictService dictService;
    private final IEmaErrorRecordService emaErrorRecordService;

    private final EmaExceptionRecordMapper emaExceptionRecordMapper;
    private final TargetParametersMapper targetParametersMapper;
    private final EmaRecordMapper recordMapper;

    //告警统计
    @Override
    public Result getAlertsCount() {
        LambdaQueryWrapper<ErrorRecord> wrapper = new LambdaQueryWrapper<>();
        LocalDateTime end = LocalDateTime.now();
        LocalDateTime start = end.minusMonths(6);
        wrapper.ge(ErrorRecord::getTime, start);
        wrapper.le(ErrorRecord::getTime, end);
        List<ErrorRecord> list = errorRecordService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Result.success();
        }

        Map<String, Long> map = list.stream()
                .collect(
                        Collectors.groupingBy(
                                record -> record.getTime().format(DateTimeFormatter.ofPattern("yyyy-MM")),
                                Collectors.counting()
                        )
                );
        return Result.success(map);
    }

    //当前状态
    @Override
    public Result getCurrentStatus() {
        LambdaQueryWrapper<EmaRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(EmaRecord::getId);
        wrapper.last("limit 1");
        EmaRecord emaRecord = recordService.getOne(wrapper);
        WorkChekcVo workChekcVo = new WorkChekcVo();
        BeanUtils.copyProperties(emaRecord, workChekcVo);
        workChekcVo.setCurrentStatus("正常");

        return Result.success(workChekcVo);
    }

    //阈值判断
    @Override
    public MonitorWaveVo getThresholdEvaluation(String name) {
        MonitorWaveVo monitorWaveVo = new MonitorWaveVo();
        LambdaQueryWrapper<Dict> targetParametersLambdaQueryWrapper = new LambdaQueryWrapper<>();
        targetParametersLambdaQueryWrapper.gt(Dict::getId, 40000);
        targetParametersLambdaQueryWrapper.lt(Dict::getId, 50000);
        targetParametersLambdaQueryWrapper.eq(Dict::getDictCode, name);
        List<Dict> list = dictService.list(targetParametersLambdaQueryWrapper);
        if (list.size() == 1) {
            Dict dict = list.get(0);
            String name1 = dict.getName();
            Float upper = targetParametersMapper.getTargetParameters(name1);
            monitorWaveVo.setUpperValue(upper);
        }
        if (list.size() == 2) {
            Dict dict1 = list.get(0);
            String name1 = dict1.getName();
            Float down = targetParametersMapper.getTargetParameters(name1);
            monitorWaveVo.setDownValue(down);
            Dict dict2 = list.get(1);
            String name2 = dict2.getName();
            Float upper = targetParametersMapper.getTargetParameters(name2);
            monitorWaveVo.setUpperValue(upper);
        }

        LambdaQueryWrapper<Dict> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(Dict::getId, 10000);
        queryWrapper.lt(Dict::getId, 20000);

        queryWrapper.eq(Dict::getName, name);
        queryWrapper.last("limit 1");
        Dict dict = dictService.getOne(queryWrapper);
        if (dict == null) throw new ImotExciption(500, "您输入参数有错，请检查后重新填入");

        String waveName = dict.getName();
        String convertName = convertName(waveName);
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime dateTime = now.minusMonths(30);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String date = dateTime.format(formatter);

        List<Map<Object, Object>> emaDataList = recordMapper.monitorWave(convertName, date);


        List<Float> numbers = new ArrayList<>();
        log.info("~~~~~~~~~~~~~~~{}", emaDataList);
        log.info("~~~~~~~~~~~~~~~{}", numbers);
// 遍历list，提取每个映射中的值
        for (Map<Object, Object> map : emaDataList) {
            Float value = (Float) map.get("value");
            numbers.add(value);
        }

        String dictCode = dict.getDictCode();
        String unit = dict.getUnit();
        monitorWaveVo.setMeasurementName(dictCode);
        monitorWaveVo.setScaleUnit(unit);
        return monitorWaveVo;
    }

    public String convertName(String name) {
        StringBuilder convertedName = new StringBuilder();

        for (char ch : name.toCharArray()) {
            if (Character.isUpperCase(ch)) {
                // 如果字符是大写字母，在前面添加横杠并转换为小写
                convertedName.append('_').append(Character.toLowerCase(ch));
            } else {
                // 如果不是大写字母，直接添加字符
                convertedName.append(ch);
            }
        }

        return convertedName.toString();
    }

    @Override
    public Map<String, Integer> getExceptionLevelDistribution(String date) {
        DateEnum dateEnum = Enum.valueOf(DateEnum.class, date.toUpperCase());

        LocalDate end = LocalDate.now();
        LocalDate start = null;
        if (dateEnum.equals(DateEnum.YEAR)) {
            start = end.withDayOfMonth(1);
        }
        if (dateEnum.equals(DateEnum.QUARTER)) {
            start = end.withDayOfYear(1);
        }
        if (dateEnum.equals(DateEnum.MONTH)) {
            int currentMonth = end.getMonthValue();
            int startMonthOfQuarter = ((currentMonth - 1) / 3) * 3 + 1;
            start = end.withMonth(startMonthOfQuarter).withDayOfMonth(1);
        }
        if (start == null) throw new ImotExciption(500, "传入参数有误");
        List<Map<String, Object>> maps = emaExceptionRecordMapper.getTheLecel(start, end);
        Map<String, Integer> levelCountMap = new HashMap<>();
        for (Map<String, Object> result : maps) {
            String level = (String) result.get("exception_level");
            Integer count = ((Number) result.get("count")).intValue();
            levelCountMap.put(level, count);
        }

        return levelCountMap;
    }

    @Override
    public Result getExceptionDetails() {
        LambdaQueryWrapper<EmaErrorRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(EmaErrorRecord::getId);
        wrapper.last("limit 50");

        List<ExceptionDetailVo> exceptionDetailVos = new ArrayList<>();
        List<EmaErrorRecord> list = emaErrorRecordService.list(wrapper);

        for (EmaErrorRecord emaErrorRecord : list) {
            ExceptionDetailVo exceptionDetailVo = new ExceptionDetailVo();
            BeanUtils.copyProperties(emaErrorRecord, exceptionDetailVo);
            exceptionDetailVos.add(exceptionDetailVo);
        }

        return Result.success(exceptionDetailVos);
    }

    @Override
    public Result getDataStatistics(String data) {
        Map<String, DataAssetVo> map = new HashMap<>();
        if (data == null) throw new ImotExciption(500, "入参为null");
        List<String> list = new ArrayList<>();
        LocalDate now = LocalDate.now();
        if (DateEnum.YEAR.toString().equals(data)) {
            int year = now.getYear();
            List<LocalDate> dates = getQuarterStartDates(year);
            LocalDate date = dates.get(0);
            LocalDate date4 = date.plusMonths(3);
            HashMap<String, DataAssetVo> hashMap = new HashMap<>();
            Boolean signal = true;
            for (int i = 0; i < dates.size() - 1; i++) {
                LocalDate start, end;
                if (i == dates.size() - 1) {
                    start = dates.get(i);
                    end = date4;
                } else {
                    start = dates.get(i);
                    end = dates.get(i + 1);
                }
                for (int j = 0; j < 20; j++) {

                }
            }

        } else if (DateEnum.MONTH.toString().equals(data)) {
            List<LocalDate> weekStartDates = this.getWeekStartDates(now);
        } else if (DateEnum.QUARTER.toString().equals(data)) {
            List<LocalDate> quarterStartAndEnd = this.getQuarterStartAndEnd(now);
        } else {
            throw new ImotExciption(500, "入参错误，请检查后重新填写");
        }

        return Result.success();
    }

    public List<LocalDate> getWeekStartDates(LocalDate date) {
        List<LocalDate> startDates = new ArrayList<>();

        // 获取当月的第一天
        LocalDate firstDayOfMonth = date.withDayOfMonth(1);
        // 将第一个星期的开始日期加入列表
        startDates.add(firstDayOfMonth);

        // 获取下个月的第一天
        LocalDate firstDayOfNextMonth = firstDayOfMonth.plusMonths(1);
        // 当前处理的日期
        LocalDate currentDate = firstDayOfMonth;

        // 遍历整个月
        while (currentDate.isBefore(firstDayOfNextMonth)) {
            // 如果是星期一（并且不是月份的第一天），将其作为新的一周的开始
            if (currentDate.getDayOfWeek().getValue() == 1 && !currentDate.equals(firstDayOfMonth)) {
                startDates.add(currentDate);
            }
            // 移动到下一天
            currentDate = currentDate.plusDays(1);
        }

        return startDates;
    }

    public List<LocalDate> getQuarterStartAndEnd(LocalDate date) {
        int year = date.getYear();
        int month = date.getMonthValue();
        LocalDate start, end;

        List<LocalDate> localDates = new ArrayList<>();
        if (month >= 1 && month <= 3) {
            // 第一季度
            start = LocalDate.of(year, 1, 1);
            end = LocalDate.of(year, 3, 31);
        } else if (month >= 4 && month <= 6) {
            // 第二季度
            start = LocalDate.of(year, 4, 1);
            end = LocalDate.of(year, 6, 30);
        } else if (month >= 7 && month <= 9) {
            // 第三季度
            start = LocalDate.of(year, 7, 1);
            end = LocalDate.of(year, 9, 30);
        } else {
            // 第四季度
            start = LocalDate.of(year, 10, 1);
            end = LocalDate.of(year, 12, 31);
        }
        localDates.add(start);
        localDates.add(end);
        return localDates;
    }

    public List<LocalDate> getQuarterStartDates(int year) {
        List<LocalDate> startDates = new ArrayList<>();

        // 第一季度开始日期
        startDates.add(LocalDate.of(year, 1, 1));

        // 第二季度开始日期
        startDates.add(LocalDate.of(year, 4, 1));

        // 第三季度开始日期
        startDates.add(LocalDate.of(year, 7, 1));

        // 第四季度开始日期
        startDates.add(LocalDate.of(year, 10, 1));

        return startDates;
    }
}

